﻿// ע�



using Grpc.Core;
using InfluxDB.Client.Api.Domain;
using IotClientService;
using IotContract.Dtos.Servers.Pushs;
using IotContract.Enums;
using IotContract.Interfaces;
using IotContract.Models.Clients;
using IotContract.Models.Jobs;
using IotContract.Models.Jobs.F29;
using IotContract.Models.Mqtt;
using IotContract.Models.Process;

using Mapster;
using MQTTnet.Server;
using Newtonsoft.Json;
using ProtoBuf;
using SqlSugar;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.Channels;
using System.Threading;
using Topshelf.Options;
using XT.Common.Extensions;
using XT.Common.Models.SignalR;
using XT.Common.Services;
using static System.Runtime.CompilerServices.RuntimeHelpers;


namespace IotServerService.Services.Mqtts;
public class MqttServerService : IMqttServerService
{
    private ILogService _logService;
    private MqttManager _mqttManager;
    private IServerMainManager _serverMainManager;
    private IEnumerable<IServerDataManager> _managers;
    private Dictionary<long, MqttPublishEquipDto> mqttPushEquips = new Dictionary<long, MqttPublishEquipDto>();
    //ProcessData是否发布控制
    private Dictionary<ProcessProviderType, MqttDataPublishStatus> mqttProcessDataStatus = new Dictionary<ProcessProviderType, MqttDataPublishStatus>();
    private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
    private List<ProcessCvData> _processCvData = new List<ProcessCvData>();
    //发布间隔时间
    private int interval = 1000;
    public MqttServerService(IServerMainManager serverMainManager, IEnumerable<IServerDataManager> managers, ILogService logService)
    {
        _logService = logService;
        
        _serverMainManager = serverMainManager;
        _managers = managers;
        
        processDatasPublishInit();
      
    }
    /// <summary>
    /// 初始化
    /// </summary>
    /// <returns></returns>
    public async Task<string> Initial()
    {
        _mqttManager = new MqttManager(_logService);
        bool result= await _mqttManager.InitAsync();

        if (result == false)
        {
            return "Error";
        }

        await StartMqtt();

        return string.Empty;

        


    }
    
    private  void processDatasPublishInit()
    {
        foreach (var item in Enum.GetValues(typeof(ProcessProviderType)))
        {
            mqttProcessDataStatus.Add((ProcessProviderType)item, 
                new MqttDataPublishStatus
                {
                    IsPublish = 1,
                    DataType = ((ProcessProviderType)item).ToString(),
                }
            );
        }
 
    }
    /// <summary>
    /// 获取MqttClient数据
    /// </summary>
    /// <param name="provider"></param>
    /// <returns></returns>
    public async Task<List<MqttClientInfo>> GetMqttClientInfos(MqttProviderCommand provider)
    {
        MqttServer mqttServer = _mqttManager.GetMqttServer();
        var res  = await mqttServer.GetClientsAsync();

        List<MqttClientInfo> ret = new List<MqttClientInfo>();
        foreach (var mqttClientInfo in res)
        {
            ret.Add(
                new MqttClientInfo
                {
                    Id = mqttClientInfo.Id,
                    Endpoint = mqttClientInfo.Endpoint,
                    ConnectedTimestamp = mqttClientInfo.ConnectedTimestamp.AddHours(8),
                    LastPacketReceivedTimestamp = mqttClientInfo.LastPacketReceivedTimestamp.AddHours(8),
                    LastPacketSentTimestamp = mqttClientInfo.LastPacketSentTimestamp.AddHours(8),
                    LastNonKeepAlivePacketReceivedTimestamp = mqttClientInfo.LastNonKeepAlivePacketReceivedTimestamp.AddHours(8),
                    ReceivedApplicationMessagesCount = mqttClientInfo.ReceivedApplicationMessagesCount,
                    SentApplicationMessagesCount = mqttClientInfo.SentApplicationMessagesCount,
                    ReceivedPacketsCount = mqttClientInfo.ReceivedPacketsCount,
                    SentPacketsCount = mqttClientInfo.SentPacketsCount
                });
        }
        return ret;
    }

    public async Task<MqttGrpcReturn> StartOrStopMqttServer(MqttProviderCommand provider)
    {
        //前端点击启动或停止按钮时，重新设置间隔时间
        interval = provider.Interval;
        if (provider == null)
        {
            return new MqttGrpcReturn
            {
                CommandResult = false
            };
        }
        MqttServer mqttServer = (MqttServer)_mqttManager.GetMqttServer();
        if (provider.Start == true)//执行启动命令
        {
            if (mqttServer.IsStarted)//已经是启动状态，直接返回
            {
                return new MqttGrpcReturn
                {
                    CommandResult = true,
                    Started = mqttServer.IsStarted
                };
            }
            await StartMqtt();

            if (mqttServer.IsStarted)
            {
                return new MqttGrpcReturn
                {
                    CommandResult = true,
                    Started = mqttServer.IsStarted
                };
            }
            return new MqttGrpcReturn
            {
                CommandResult = false,
                Started = mqttServer.IsStarted
            };
        }
        if (provider.Start == false)//执行停止命令
        {
            if (!mqttServer.IsStarted)//已经是停止状态，直接返回
            {
                return new MqttGrpcReturn
                {
                    CommandResult = true,
                    Started = mqttServer.IsStarted
                };
            }
            await StopMqtt();
            if (!mqttServer.IsStarted)
            {
                return new MqttGrpcReturn
                {
                    CommandResult = true,
                    Started = mqttServer.IsStarted
                };
            }
            return new MqttGrpcReturn
            {
                CommandResult = false,
                Started = mqttServer.IsStarted
            };
        }

        return new MqttGrpcReturn
        {
            CommandResult = false,
            Started = mqttServer.IsStarted
        };
    }

    public async Task<MqttGrpcReturn> GetMqttServerStatus()
    {
        MqttServer mqttServer = _mqttManager.GetMqttServer();

        return new MqttGrpcReturn
        {
            Started = mqttServer.IsStarted,
            Interval = interval,
        };
    }
    /// <summary>
    /// 获取业务数据
    /// </summary>
    /// <returns></returns>
    public async Task MqttPushProcessData()
    {

        string json = string.Empty;
        var items = Enum.GetValues<ProcessProviderType>();
        foreach (var processProviderType in items)
        {
            
            
            if (processProviderType == ProcessProviderType.Bcr)
            {
                var bcrs = await _serverMainManager.GetEquips<PushBcrDto>(new IotContract.Models.Clients.ClientRequestCommand
                {
                    RequestType = IotEquipType.BCR.ToString(),
                    ProtobufType = IotProtobufType.HBC_BCR.ToString()
                });

                if (bcrs == null || bcrs.Count == 0) { continue; }

                if (mqttProcessDataStatus[processProviderType].IsPublish == 1)
                {
                    json = JsonConvert.SerializeObject(bcrs.Where(x=>x.Connection==true));
                        
                }
            }
            else if(processProviderType == ProcessProviderType.Cv || processProviderType==ProcessProviderType.Sc || processProviderType == ProcessProviderType.Other)
            {
                var processDatas = await _serverMainManager.GetProcessDatas(new ProcessProviderCommand()
                {
                    ProviderType = processProviderType
                });
                if (processDatas == null || processDatas.Count == 0) { continue; }

                if (mqttProcessDataStatus[processProviderType].IsPublish == 1)
                {
                    json = JsonConvert.SerializeObject(processDatas.Where(x=>x.Connection==true));
                }
            }

            if (json.IsNotNullOrEmpty() && json!="[]")
            {
                await _mqttManager.PublishData(processProviderType.ToString(), json, 1, false, "Server");
            }
        }
    }

    /// <summary>
    /// 单个业务数据是否参与Mqtt发布
    /// </summary>
    /// <param name="provider"></param>
    /// <returns></returns>
    public  MqttGrpcReturn StartOrStopMqttProcessData(MqttProviderCommand provider)
    {
        
        if (provider == null)
        {
            return new MqttGrpcReturn
            {
                CommandResult = false
            };
        }
       
        if (provider.EquipType.IsNotNullOrEmpty())//执行启动、停止命令
        {
            mqttProcessDataStatus[Enum.Parse<ProcessProviderType>(provider.EquipType)].IsPublish = provider.Start ? 1 :0;
            mqttProcessDataStatus[Enum.Parse<ProcessProviderType>(provider.EquipType)].interval = provider.Interval;

            return new MqttGrpcReturn
            {
                CommandResult = true,
                Started = mqttProcessDataStatus[Enum.Parse<ProcessProviderType>(provider.EquipType)].IsPublish == 1?true:false,
            };
        }
        return new MqttGrpcReturn
        {
            CommandResult = false
            
        };
    }

    public MqttGrpcReturn GetDataPublishStatus()
    {
        return new MqttGrpcReturn()
        { 
            CommandResult = true, 
            DataPublishStatus = mqttProcessDataStatus.Values.ToList<MqttDataPublishStatus>() 
        };
    }

    public async Task<MqttGrpcReturn>  StartMqtt()
    {
        if (_cancellationTokenSource != null)
        {
            _cancellationTokenSource.Cancel();
            await Task.Delay(1000);
        }
        _cancellationTokenSource = new CancellationTokenSource();
        MqttServer mqttServer = _mqttManager.GetMqttServer();

        if (!mqttServer.IsStarted)//MqttServer如未启动，先启动
        {
            await _mqttManager.StartAsync();
        }
        // 定时获取业务数据、发布
        Task.Run(async () =>
        {
            try 
            {
                while (true)
                {
                    if (_cancellationTokenSource.IsCancellationRequested) 
                    {
                        break; 
                    }
                    await MqttPushProcessData();
                    
                    await Task.Delay(interval);
                }
            }
            catch (Exception ex)
            {
               _logService.LogError("Mqtt获取业务数据异常", ex);
            }
        }, _cancellationTokenSource.Token);
        
        return new MqttGrpcReturn()
        {
            CommandResult = true,
        };
    }

    public async Task<MqttGrpcReturn> StopMqtt()
    {
        try
        {
            //停止各类数据发布
            //foreach(var processType in mqttProcessDataStatus.Values)
            //{
            //    processType.IsPublish = 0;
            //}
            MqttServer mqttServer = _mqttManager.GetMqttServer();
            //关闭MqttServer
            if (mqttServer.IsStarted)
            {
                await _mqttManager.StopAsync();
            }
            _cancellationTokenSource.Cancel();
        } 
        catch (Exception ex)
        {
            _logService.LogError("Mqtt停止异常", ex);
        }
        return new MqttGrpcReturn()
        {
            CommandResult = true,
        };
    }
    
}
